package com.hy.mydesktop.client.component.factory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.data.BaseModel;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.BaseTreeLoader;
import com.extjs.gxt.ui.client.data.BaseTreeModel;
import com.extjs.gxt.ui.client.data.DataProxy;
import com.extjs.gxt.ui.client.data.DataReader;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.data.TreeLoader;
import com.extjs.gxt.ui.client.data.TreeModel;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.StoreFilterField;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanelSelectionModel;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.CheckCascade;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.CheckNodes;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.hy.mydesktop.client.component.event.AppEvents;
import com.hy.mydesktop.client.component.meta.TreePanelModulesModelEnum;
import com.hy.mydesktop.client.component.mvc.event.EventStructureMetaModel;
import com.hy.mydesktop.client.rpc.GreetingService;
import com.hy.mydesktop.client.rpc.GreetingServiceAsync;
import com.hy.mydesktop.client.rpc.ServiceInvoker;
import com.hy.mydesktop.client.rpc.ServiceInvokerAsync;
import com.hy.mydesktop.client.rpc.reader.GxtToSeamServiceResultListReader;
import com.hy.mydesktop.client.rpc.reader.GxtToSeamServiceResultReader;
import com.hy.mydesktop.client.rpc.reader.GxtToSeamServiceResultTreeReader;
import com.hy.mydesktop.shared.persistence.domain.gxt.GxtComponentMetaNodeModel;
import com.hy.mydesktop.shared.rpc.meta.GxtToSeamServiceParameter;
import com.hy.mydesktop.shared.rpc.meta.GxtToSeamServiceResult;
import com.hy.mydesktop.shared.rpc.meta.GxtToSeamServiceTreeNode;

/**
 * 
 * <ul>
 * <li>开发作者：冬超</li>
 * <li>设计日期：2010-8-30；时间：下午01:11:56</li>
 * <li>类型名称：ReorderingGridFactory</li>
 * <li>设计目的：</li>
 * </ul>
 * <ul>
 * <b>修订编号：</b>
 * <li>修订日期：</li>
 * <li>修订作者：</li>
 * <li>修订原因：</li>
 * <li>修订内容：</li>
 * </ul>
 */
public class TreePanelModulesFactory {

	private static ServiceInvokerAsync service = GWT
			.create(ServiceInvoker.class);
	//private static GreetingServiceAsync tservice = GWT.create(GreetingService.class);
	// 数据加载
	//private static TreeStore<ModelData> store;
	private static TreeStore<GxtToSeamServiceTreeNode> treeStore;
	// 面板
	private static ContentPanel treePanelContainer;

	//private static TreeLoader<ModelData> loader;
	private static TreeLoader<GxtToSeamServiceTreeNode> treeLoader;

	private static GxtToSeamServiceParameter gxtToSeamServiceParameter;

//	private static GxtToSeamServiceResultTreeReader<List<GxtToSeamServiceTreeNode>> reader = new GxtToSeamServiceResultTreeReader<List<GxtToSeamServiceTreeNode>>();
	private static GxtToSeamServiceResultTreeReader<GxtToSeamServiceResult> treeReader = new GxtToSeamServiceResultTreeReader<GxtToSeamServiceResult>();
//	private static GxtToSeamServiceResultListReader<GxtToSeamServiceResult> listReader = new GxtToSeamServiceResultListReader<GxtToSeamServiceResult>();

	public static ContentPanel createTreePanelModule(
			GxtComponentMetaNodeModel gxtComponentMetaNodeModel) {

		return configureTreePanel(gxtComponentMetaNodeModel);
	}

	/**
	 * 
	 * 
	 * @param gxtComponentMetaNodeModel
	 * @return
	 */
	private static ContentPanel configureTreePanel(
			GxtComponentMetaNodeModel gxtComponentMetaNodeModel) {

		treePanelContainer = ContentPanelFactory.createContentPanel(gxtComponentMetaNodeModel);
		treePanelContainer.setScrollMode(Scroll.AUTO);
		final TreePanel<GxtToSeamServiceTreeNode> treePanel = createDefaultBaseTreePanel(
				treePanelContainer,gxtComponentMetaNodeModel);

		
		TreePanelSelectionModel<GxtToSeamServiceTreeNode> sm = new TreePanelSelectionModel<GxtToSeamServiceTreeNode>(){
			 //@Override
			  protected void onSelectChange(GxtToSeamServiceTreeNode model, boolean select) {
			   // tree.getView().onSelectChange(model, select);
				 super.onSelectChange(model, select);
				 if (select) {
					//com.google.gwt.user.client.Window.alert(model.get("name").toString());
					/**
					 * 如何定位：EventModel
					 * 如何传输数据
					 * 传递哪些数据：字段信息，表格数据信息
					 * 定义什么样的结构，可以合适的传输上述信息
					 * 方案1：
					 * 传输两个GxtToSeamServiceParameter（List）
					 * 方案2：
					 * 传输一个GxtToSeamServiceParameter（当Grid收到此对象后，向后台
					 * 发出请求，获得方案1中的两个GxtToSeamServiceParameter，而后，再依次发出
					 * 刚才的两个GxtToSeamServiceParameter对应的请求）
					 * 
					 * 暂定方案1
					 * 
					 * 注：由于鼠标联动的需求，需要修改GxtToSeamServiceTreeNode的机构
					 * 
					 */
					//List<GxtToSeamServiceParameter>
					EventStructureMetaModel eventStructureMetaModel = model.getEventStructureMetaModel();
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("eventstructuremetamodel", eventStructureMetaModel);
					Dispatcher.get().dispatch(AppEvents.GRID_RELOAD,map);
				}
			  }

		};
		treePanel.setSelectionModel(sm);
//		treePanel = AbstractComponetFactory.configureAbstractComponet(treePanel, gxtComponentMetaNodeModel);
		AbstractComponetFactory.configureAbstractComponet(treePanel, gxtComponentMetaNodeModel);



		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.LOADERDATA.name()
				.toLowerCase()) != null) {
			gxtToSeamServiceParameter = new GxtToSeamServiceParameter();
			gxtToSeamServiceParameter
					.setServiceComponentName("com.test.server.business.PersonService");
//			gxtToSeamServiceParameter.setServiceMethodName("listPerson4");
			gxtToSeamServiceParameter.setServiceMethodName("listT");
			BaseModel[] methodArguments = new BaseModel[1];
			methodArguments[0] = new BaseModel();
			methodArguments[0].set("init", null);
			gxtToSeamServiceParameter.setMethodArguments(methodArguments);
		}

		/*final TreePanel<ModelData> treepanel = createDefaultBaseTreePanel(
				gxtComponentMetaNodeModel, table);*/
		
			
		
		// 高度
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.HIGHT1.name()
				.toLowerCase()) != null) {
			Integer height = (Integer) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.HIGHT1.name().toLowerCase());
			treePanel.setHeight((int) height);

		}
		// 宽度
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.WIDTH1.name()
				.toLowerCase()) != null) {
			Integer width = (Integer) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.WIDTH1.name().toLowerCase());
			treePanel.setWidth((int) width);

		}
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.AUTOLOAD.name()
				.toLowerCase()) != null) {
			Boolean autoLoad = (Boolean) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.AUTOLOAD.name().toLowerCase());
			treePanel.setAutoLoad(autoLoad);

		}
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.ADDBUTTON.name()
				.toLowerCase()) != null) {
			Button expend = ButtonFactory
					.createButton(gxtComponentMetaNodeModel);
			expend.addListener(Events.OnClick, new Listener<ButtonEvent>() {

				@Override
				public void handleEvent(ButtonEvent be) {
					treePanel.expandAll();

				}
			});
			Button collapse = ButtonFactory
					.createButton(gxtComponentMetaNodeModel);
			collapse.addListener(Events.OnClick, new Listener<ButtonEvent>() {

				@Override
				public void handleEvent(ButtonEvent be) {
					treePanel.collapseAll();

				}
			});

			treePanelContainer.add(expend);
			treePanelContainer.add(collapse);

		}
		// 需要把方filter加到面板上才能够使用
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.FILTER.name()
				.toLowerCase()) != null) {
			/*StoreFilterField<ModelData> filter = new StoreFilterField<ModelData>() {

				@Override
				protected boolean doSelect(Store<ModelData> store,
						ModelData parent, ModelData record, String property,
						String filter) {

					return false;
				}

			};
			filter.bind(store);*/
			StoreFilterField<GxtToSeamServiceTreeNode> filter = new StoreFilterField<GxtToSeamServiceTreeNode>() {

				@Override
				protected boolean doSelect(
						Store<GxtToSeamServiceTreeNode> store,
						GxtToSeamServiceTreeNode parent,
						GxtToSeamServiceTreeNode record, String property,
						String filter) {
					return false;
				}

				

			};
			filter.bind(treeStore);
			treePanelContainer.setTopComponent(filter);
		}

		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.TRACKMOUSEOVER
				.name().toLowerCase()) != null) {
			Boolean trackMouseOver = (Boolean) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.TRACKMOUSEOVER.name().toLowerCase());
			treePanel.setTrackMouseOver(trackMouseOver);

		}
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.BORDER.name()
				.toLowerCase()) != null) {
			Boolean show = (Boolean) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.BORDER.name().toLowerCase());
			treePanel.setBorders(show);

		}
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.CHECKBOXSTYLE
				.name().toLowerCase()) != null) {
			String checkable = (String) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.CHECKBOXSTYLE.name().toLowerCase());
			if (checkable.equals("parents")) {
				treePanel.setCheckStyle(CheckCascade.PARENTS);
			} else if (checkable.equals("children")) {
				treePanel.setCheckStyle(CheckCascade.CHILDREN);

			} else {
				treePanel.setCheckStyle(CheckCascade.NONE);
			}
		}
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.CHECKBOXNODE
				.name().toLowerCase()) != null) {
			String checkable = (String) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.CHECKBOXNODE.name().toLowerCase());
			if (checkable.equals("parent")) {
				treePanel.setCheckNodes(CheckNodes.PARENT);
			} else if (checkable.equals("leaf")) {
				treePanel.setCheckNodes(CheckNodes.LEAF);

			} else if (checkable.equals("both")) {
				treePanel.setCheckNodes(CheckNodes.BOTH);
			}
		}
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.CHECKBOX.name()
				.toLowerCase()) != null) {
			Boolean checkable = (Boolean) gxtComponentMetaNodeModel
					.get(TreePanelModulesModelEnum.CHECKBOX.name().toLowerCase());
			treePanel.setCheckable(checkable);

		}
		//设置菜单
		if (gxtComponentMetaNodeModel.get(TreePanelModulesModelEnum.MENU.name()
				.toLowerCase()) != null) {
			Menu contextMenu = MenuFactory
					.createMenu(gxtComponentMetaNodeModel);
			Component component = contextMenu.getItem(0);

			/*
			 * MenuItem insert = new MenuItem(); insert.setText("Insert Item");
			 * insert.addSelectionListener(new SelectionListener<MenuEvent>() {
			 * public void componentSelected(MenuEvent ce) { ModelData folder =
			 * treepanel.getSelectionModel().getSelectedItem(); if (folder !=
			 * null) { RPCTreeModel child = new RPCTreeModel("Add Child ","");
			 * store.add(folder, child, false); treepanel.setExpanded(folder,
			 * true); } } }); contextMenu.add(insert); MenuItem remove = new
			 * MenuItem(); remove.setText("Remove Selected");
			 * remove.addSelectionListener(new SelectionListener<MenuEvent>() {
			 * public void componentSelected(MenuEvent ce) { List<ModelData>
			 * selected = treepanel.getSelectionModel().getSelectedItems(); for
			 * (ModelData sel : selected) { store.remove(sel); } } });
			 * contextMenu.add(remove);
			 */
			treePanel.setContextMenu(contextMenu);
			;
		}

		return treePanelContainer;
	}

	private static TreePanel<GxtToSeamServiceTreeNode> createDefaultBaseTreePanel(ContentPanel treePanelContainer,
			GxtComponentMetaNodeModel gxtComponentMetaNodeModel) {

		
//		store = getTreePanelStore(table);
		treeStore = getTreePanelStore();

		//TreePanel<ModelData> treePanel = new TreePanel<ModelData>(store);
		TreePanel<GxtToSeamServiceTreeNode> treePanel = new TreePanel<GxtToSeamServiceTreeNode>(treeStore);
		treePanel.setDisplayProperty("name");
		//loader.load();
		treePanelContainer.add(treePanel);
		return treePanel;
		/*treePanelContainer = ContentPanelFactory
		.createContentPanel(gxtComponentMetaNodeModel);

		TreeStore<ModelData> treeStore = new TreeStore<ModelData>();
		treeStore.add(getTreeModel(), true);
		TreePanel<ModelData> treePanel = new TreePanel<ModelData>(treeStore);
		treePanel.setDisplayProperty("name");
		//loader.load();
		treePanelContainer.add(treePanel);
		return treePanel;*/
	}
	private static TreeStore<GxtToSeamServiceTreeNode> getTreePanelStore() {
//		RpcProxy<GxtToSeamServiceResult> proxy = new RpcProxy<GxtToSeamServiceResult>() {
			RpcProxy<GxtToSeamServiceResult> proxy = new RpcProxy<GxtToSeamServiceResult>() {
			@Override
			protected void load(Object loadConfig,
					AsyncCallback<GxtToSeamServiceResult> callback) {
				//service.callService(gxtToSeamServiceParameter, callback);
				if (loadConfig==null) {
					service.callService(gxtToSeamServiceParameter, callback);
				}else {
					/*GxtToSeamServiceParameter subGxtToSeamServiceParameter = new GxtToSeamServiceParameter();
					subGxtToSeamServiceParameter
					.setServiceComponentName("com.test.server.business.PersonService");
					subGxtToSeamServiceParameter.setServiceMethodName("listT_T");
					ModelData[] methodArguments = new BaseModelData[1];
					methodArguments[0] = new BaseModel();
					methodArguments[0].set("init", null);
					subGxtToSeamServiceParameter.setMethodArguments(methodArguments);
					service.callService(subGxtToSeamServiceParameter, callback);*/
					Object parent = loadConfig;
					GxtToSeamServiceTreeNode gxtToSeamServiceTreeNode = null;
					GxtToSeamServiceParameter tempGxtToSeamServiceParameter = null;
					if(parent instanceof GxtToSeamServiceTreeNode){
						gxtToSeamServiceTreeNode =((GxtToSeamServiceTreeNode) parent);
						tempGxtToSeamServiceParameter = new GxtToSeamServiceParameter();
						tempGxtToSeamServiceParameter.setMethodArguments(gxtToSeamServiceTreeNode.getMethodArguments());
						tempGxtToSeamServiceParameter.setServiceComponentName(gxtToSeamServiceTreeNode.getServiceComponentName());
						tempGxtToSeamServiceParameter.setServiceMethodName(gxtToSeamServiceTreeNode.getServiceMethodName());
					    //把gxtToSeamServiceTreeNode，解析成tempGxtToSeamServiceParameter，再次调用Rpc
						service.callService(tempGxtToSeamServiceParameter, callback);
					}
				}
				
				
			}
		};
		
		// 判断是否有孩子
		//loader = new BaseTreeLoader<ModelData>(proxy,listreader);
		//loader = new MyBaseTreeLoader<GxtToSeamServiceTreeNode>(proxy,reader);
		//store = new TreeStore<ModelData>(loader);
//		treeLoader = new MyBaseTreeLoader<GxtToSeamServiceTreeNode>(proxy,reader);
		
		/**
		 * TreePanel控件的节点类型，必须是GxtToSeamServiceTreeNode
		 * hasChildren()，用来判断当前GxtToSeamServiceTreeNode，是否有子节点
		 */
		treeLoader = new BaseTreeLoader<GxtToSeamServiceTreeNode>(proxy,treeReader){
			@Override
			public boolean hasChildren(GxtToSeamServiceTreeNode parent) {
				if(parent instanceof GxtToSeamServiceTreeNode){
					//System.err.println("#####MyBaseTreeLoader.hasChildren(M parent) is ................"+((GxtToSeamServiceTreeNode) parent).hasChildren());	 
					return((GxtToSeamServiceTreeNode) parent).hasChildren();
				}
				return false;
			}
			/**
			 * 流程
			 * 单击某一节点
			 * TreePanel响应此事件
			 * 调用Loader的hasChildren方法，判断是否有孩子
			 * 如果有孩子，调用Loader的loadChildren方法---load----Rpc.load
			 */
			/**
			 * 此方法用于加载数据
			 * 将当前节点对象GxtToSeamServiceTreeNode，作为参数loadConfig，
			 * 传入RpcProxy的load方法和Rpc的load方法。（通常是用多次调用Rpc，例如异步树和分页表格）
			 * 
			 * 
			 * @see com.extjs.gxt.ui.client.data.BaseTreeLoader#loadChildren(com.extjs.gxt.ui.client.data.ModelData)
			 */
			@Override
			public boolean loadChildren(GxtToSeamServiceTreeNode parent) {
			    children.add(parent);
				//System.err.println("#####MyBaseTreeLoader.loadChildren(M parent) is running ................"+parent);	 
			    return load(parent);
			  }
			
			/*@Override
			public boolean loadChildren(GxtToSeamServiceTreeNode parent) {
				System.err.println("#####MyBaseTreeLoader.loadChildren(M parent) is running ................");	 
				GxtToSeamServiceTreeNode gxtToSeamServiceTreeNode = null;
				GxtToSeamServiceParameter gxtToSeamServiceParameter = null;
				//把M parent 转换成GxtToSeamServiceParameter
				if(parent instanceof GxtToSeamServiceTreeNode){
					gxtToSeamServiceTreeNode =((GxtToSeamServiceTreeNode) parent);
					gxtToSeamServiceParameter = new GxtToSeamServiceParameter();
					gxtToSeamServiceParameter.setMethodArguments(gxtToSeamServiceTreeNode.getMethodArguments());
					gxtToSeamServiceParameter.setServiceComponentName(gxtToSeamServiceTreeNode.getServiceComponentName());
					gxtToSeamServiceParameter.setServiceMethodName(gxtToSeamServiceTreeNode.getServiceMethodName());
					children.add(parent);
				    System.err.println("#####MyBaseTreeLoader.loadChildren(M parent) is over ................");	 		
				    return load(gxtToSeamServiceParameter);
				}
				children.add(parent);
				return load(gxtToSeamServiceParameter);
				
			}*/
		};
		treeStore = new TreeStore<GxtToSeamServiceTreeNode>(treeLoader);
		//treeStore.getLoader().load();
		
		
		// 排序
		//store.setStoreSorter(new StoreSorter<ModelData>());
		return treeStore;
	}
	
	private static TreeModel getTreeModel(){
		TreeModel root = new BaseTreeModel();
		root.set("name", "根节点");
		TreeModel child = new BaseTreeModel();
		child.set("name", "子节点");
		child.setParent(root);
		root.add(child);
			TreeModel subchild = new BaseTreeModel();
			subchild.set("name", "sub子节点");
			subchild.setParent(child);
			child.add(subchild);
		
		return root;
	}
}
